package com.dp.mallchat.common.user.service.impl;

import cn.hutool.extra.spring.SpringUtil;
import com.dp.mallchat.common.common.annotation.MyRedissonLock;
import com.dp.mallchat.common.common.domain.enums.YesOrNoEnum;
import com.dp.mallchat.common.common.lock.LockService;
import com.dp.mallchat.common.user.dao.UserBackpackDao;
import com.dp.mallchat.common.user.domain.user.entity.UserBackpack;
import com.dp.mallchat.common.user.domain.user.enums.IdempotenceEnum;
import com.dp.mallchat.common.user.service.UserBackpackService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @Author: dupeng
 * @CreateTime: 2024-06-05  19:38
 * @Description: TODO
 */
@Service
@Slf4j
public class UserBackpackServiceImpl extends UserBackpackDao implements UserBackpackService {

    @Autowired
    private UserBackpackDao userBackpackDao;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private LockService lockService;

    /**
     * 向用户背包发放物品
     *
     * @param uId             用户id
     * @param itemId          物品id
     * @param idempotenceEnum 幂等类型
     * @param businessId      业务id
     */
    @Override
    @SneakyThrows
    public void acquireItem(Long uId, Long itemId, IdempotenceEnum idempotenceEnum, String businessId) {
        //获取唯一幂等号
        String idempotence = getIdempotence(itemId, idempotenceEnum.getType(), businessId);
        //分布式锁执行业务
        SpringUtil.getBean(UserBackpackServiceImpl.class).executeAcquireItem(idempotence, uId, itemId);
    }


    @MyRedissonLock(key = "#idempotence", waitTime = 5000)
    public void executeAcquireItem(String idempotence, Long uId, Long itemId) {
        UserBackpack userBackpack = userBackpackDao.getByIdempontence(idempotence);
        if (Objects.nonNull(userBackpack)) {
            // 不为空说明已经拥有此物品，直接返回
            return;
        }

        //发放物品
        UserBackpack insert = UserBackpack.builder()
                .uid(uId)
                .itemId(itemId)
                .idempotent(idempotence)
                .status(YesOrNoEnum.NO.getStatus())
                .build();
        userBackpackDao.save(insert);
    }


    // 提取分布式锁统一入口方法
//    @Override
//    @SneakyThrows
//    public void acquireItem(Long uId, Long itemId, IdempotenceEnum idempotenceEnum, String businessId) {
//        //获取唯一幂等号
//        String idempotence = getIdempotence(itemId, idempotenceEnum.getType(), businessId);
//        //分布式锁执行业务
//        lockService.runWithLock(idempotence, () -> {
//            //判断是否拥有此物品
//            UserBackpack userBackpack = userBackpackDao.getByIdempontence(idempotence);
//            if (Objects.nonNull(userBackpack)) {
//                // 不为空说明已经拥有此物品，直接返回
//                return;
//            }
//            //TODO 可做物品数量等处理,后续完善
//
//            //发放物品
//            UserBackpack insert = UserBackpack.builder()
//                    .uid(uId)
//                    .itemId(itemId)
//                    .idempotent(idempotence)
//                    .status(YesOrNoEnum.NO.getStatus())
//                    .build();
//            userBackpackDao.save(insert);
//        });
//    }


    // 原生分布式锁
//    @Override
//    public void acquireItem(Long uId, Long itemId, IdempotenceEnum idempotenceEnum, String businessId) {
//        //获取唯一幂等号
//        String idempotence = getIdempotence(itemId, idempotenceEnum.getType(), businessId);
//        RLock lock = redissonClient.getLock(idempotence);
//        lock.lock();
//        try{
//            //判断是否拥有此物品
//            UserBackpack userBackpack = userBackpackDao.getByIdempontence(idempotence);
//            if (Objects.nonNull(userBackpack)){
//                // 不为空说明已经拥有此物品，直接返回
//                return;
//            }
//            //TODO 可做物品数量等处理,后续完善
//
//            //发放物品
//            UserBackpack insert = UserBackpack.builder()
//                    .uid(uId)
//                    .itemId(itemId)
//                    .idempotent(idempotence)
//                    .status(YesOrNoEnum.NO.getStatus())
//                    .build();
//            userBackpackDao.save(insert);
//        }finally {
//            lock.unlock();
//        }
//    }


    private String getIdempotence(Long itemId, Integer type, String businessId) {
        return String.format("%d_%d_%s", itemId, type, businessId);
    }
}
